package jhunter.context;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import jhunter.common.exception.ConfigException;
import jhunter.common.id.UuidShorter;
import jhunter.dao.DaoFactory;
import jhunter.dao.EntityContainer;
import jhunter.dao.ddl.SchemaGenerator;
import jhunter.dao.dialect.Dialect;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.FileResourceLoader;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;

import schema.Environment;
import schema.ext.AppExt;
import schema.vo.app.DataSourceConfig;
import schema.vo.app.DataSourceProperty;

import com.alibaba.druid.pool.DruidDataSource;

public class AppContext {

	private AppExt appExt;

	private UuidShorter uuidShorter;

	private DataSource dataSource;

	private DataSourceTransactionManager dataSourceTransactionManager;

	private Dialect dialect;

	private EntityContainer entityContainer;

	private SchemaGenerator schemaGenerator;

	private DaoFactory daoFactory;

	private VelocityEngine velocityEngine;

	private String viewLibPath;

	public AppContext(AppExt appExt) {
		super();
		this.appExt = appExt;
		init();
	}

	private void init() {

		uuidShorter = new UuidShorter(1);

		DataSourceConfig ds = appExt.getApp().getDataSourceConfig();

		List<DataSourceProperty> props = ds.getDataSourceProperty();

		DruidDataSource dd = new DruidDataSource();
		Map<String, String> map = new HashMap<String, String>();
		for (DataSourceProperty dataSourceProperty : props) {
			map.put(dataSourceProperty.getName(), dataSourceProperty.getValue());
		}

		setPropertyIfHas(dd, map);

		dataSource = new TransactionAwareDataSourceProxy(dd);
		dataSourceTransactionManager = new DataSourceTransactionManager(dd);
		entityContainer = new EntityContainer();
		entityContainer.setUuidShorter(uuidShorter);

		schemaGenerator = new SchemaGenerator();
		setPropertyIfHas(schemaGenerator, map);

		try {
			dialect = (Dialect) Class.forName(map.get("jHunterDialect")).newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
			throw new ConfigException(e);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			throw new ConfigException(e);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			throw new ConfigException(e);
		}
		daoFactory = new DaoFactory();
		daoFactory.setEntityContainer(entityContainer);
		daoFactory.setDataSource(dataSource);
		daoFactory.setDialect(dialect);

		velocityEngine = new VelocityEngine();
		velocityEngine.addProperty(Velocity.RESOURCE_LOADER, "file");
		velocityEngine.addProperty("file.resource.loader.class", FileResourceLoader.class.getName());
		velocityEngine.addProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "");
		velocityEngine.init();

		String p = Environment.getDefaultClassLoader().getResource("/view/lib.vm").getFile();
		viewLibPath = FilenameUtils.normalize(p, true);
	}

	protected void setPropertyIfHas(Object bean, Map<String, String> values) {

		for (String key : values.keySet()) {
			try {
				BeanUtils.setProperty(bean, key, values.get(key));
			} catch (Exception e) {
				continue;
			}
		}

	}

	public AppExt getAppExt() {
		return appExt;
	}

	public DataSource getDataSource() {
		return dataSource;
	}

	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}

	public DaoFactory getDaoFactory() {
		return daoFactory;
	}

	public void setDaoFactory(DaoFactory daoFactory) {
		this.daoFactory = daoFactory;
	}

	public DataSourceTransactionManager getDataSourceTransactionManager() {
		return dataSourceTransactionManager;
	}

	public void setDataSourceTransactionManager(DataSourceTransactionManager dataSourceTransactionManager) {
		this.dataSourceTransactionManager = dataSourceTransactionManager;
	}

	public UuidShorter getUuidShorter() {
		return uuidShorter;
	}

	public void setUuidShorter(UuidShorter uuidShorter) {
		this.uuidShorter = uuidShorter;
	}

	public Dialect getDialect() {
		return dialect;
	}

	public void setDialect(Dialect dialect) {
		this.dialect = dialect;
	}

	public EntityContainer getEntityContainer() {
		return entityContainer;
	}

	public void setEntityContainer(EntityContainer entityContainer) {
		this.entityContainer = entityContainer;
	}

	public SchemaGenerator getSchemaGenerator() {
		return schemaGenerator;
	}

	public void setSchemaGenerator(SchemaGenerator schemaGenerator) {
		this.schemaGenerator = schemaGenerator;
	}

	public VelocityEngine getVelocityEngine() {
		return velocityEngine;
	}

	public void setVelocityEngine(VelocityEngine velocityEngine) {
		this.velocityEngine = velocityEngine;
	}

	public String getViewLibPath() {
		return viewLibPath;
	}

	public void setViewLibPath(String viewLibPath) {
		this.viewLibPath = viewLibPath;
	}
}
